#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>

typedef struct arg
{
	int sockfd;
	struct sockaddr_in* client;
}arg;

int func(void* a)
{
	arg* p=(arg*)a;	
	char buf[128];
	while(1)
	{
		ssize_t rec=recv(p->sockfd,buf,sizeof(buf),0);
		if(rec < 0)
		{
			perror("recv");
			return 4;
		}
		if(rec == 0)
		{
			break;
		}
		buf[rec]=0;
		printf("[%s,%d]: > %s\n",inet_ntoa((*(p->client)).sin_addr),\
				ntohs((*(p->client)).sin_port),buf);

		send(p->sockfd,buf,strlen(buf),0);
	}
	free(p);
	close(p->sockfd);
}

int main(int argc,char* argv[])
{
	if(argc != 3)
	{
		perror("argc");
		return 1;
	}

	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	if(sockfd<0)
	{
		perror("socket");
		return 2;
	}

	struct sockaddr_in local;
	local.sin_family=AF_INET;
	local.sin_port=htons(atoi(argv[2]));
	local.sin_addr.s_addr=inet_addr(argv[1]);

	if(bind(sockfd,(struct sockaddr*)&local,sizeof(local))<0)
	{
		perror("bind");
		return 3;
	}

	if(listen(sockfd,5)==-1)
	{
		perror("listen");
		return 5;
	}

	while(1)
	{
		struct sockaddr_in peer;
		socklen_t len=sizeof(peer);
		int new_sockfd=accept(sockfd,(struct sockaddr*)&peer,&len);
		if(new_sockfd<0)
		{
			perror("accept");
			return 6;
		}
		arg* a=(arg*)malloc(sizeof(arg));
		a->sockfd=new_sockfd;
		a->client=&peer;
		pthread_t thread=0;
		pthread_create(&thread,NULL,func,(void*)a);
		pthread_detach(thread);
	}
	close(sockfd);

	return 0;
}
